//---------------------------------------------------------------------------------
// Copyright (c) 2008 Metaphor Game Engine Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

//Singleton class is from the following site:
//http://www.drizzle.com/~scottb/publish/gpgems1_singleton.htm
//
//The following modifications have been made:
// - used static_cast method described here: 
//   http://www.drizzle.com/~scottb/publish/gpgems1_singleton_notes.htm
//
//The singleton class is assumed to be free software

#include <cassert>

#ifndef __SINGLETON_H__
#define __SINGLETON_H__


//! To make a class into a singleton publically extend this (T = the class to extend).

/// Use T::getSingleton() or T::getSingletonPtr() to get the object. It is the
/// users responsibility to create T somewhere exactly once within their application.
/// 
/// Example usage:
///
///    MyClass instance;
///
///    // can be called from anywhere as long as instance is still alive
///
///    MyClass::getSingleton().doSomething(); 
template <typename T> class VLSingleton
{
  static T* ms_Singleton;
public:

  //! Asserts if the extending class is created more than once
  VLSingleton( void )
  {
    assert( !ms_Singleton && 
      "A Singleton<T> extending class has been initialized more than once.");
    ms_Singleton = static_cast <T*> (this);
  }

  //! Singleton no longer is available if the instance is destroyed
  ~VLSingleton( void )
  {  
    // To be destructed the singleton must have been made once already
    assert( ms_Singleton ); 
    ms_Singleton = 0;  
  }

  //! Get reference to T
  static T& getSingleton( void )
  {  
    assert( ms_Singleton && "The singleton hasn't been instantiated anywhere yet");  
    return ( *ms_Singleton ); 
  }

  //! Get pointer to T
  static T* getSingletonPtr( void )
  {  return ( ms_Singleton );  }
};

template <typename T> T* VLSingleton<T>::ms_Singleton = 0;

#endif